home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 31
/
Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso
/
Aminet
/
dev
/
c
/
vbccwossrc.lha
/
vbcc
/
pasm
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-03-07
|
9KB
|
311 lines
/* $VER: pasm main.c V0.7 (02.01.98)
*
* This file is part of pasm, a portable PowerPC assembler.
* Copyright (c) 1997-98 Frank Wille
*
* pasm is freeware and part of the portable and retargetable ANSI C
* compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
* pasm may be freely redistributed as long as no modifications are
* made and nothing is charged for it. Non-commercial usage is allowed
* without any restrictions.
* EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
* SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
*
*
* v0.7 (02.01.98) phx
* Allow more than two assembler passes, as required for
* optimizations.
* Option -O (output format) was renamed to -F. New option -O for
* enabling optimizations.
* Output format 3 is ADOS (like EHF, but doesn't use HUNK_PPC_CODE).
* v0.6 (30.10.97) phx
* Options to disable warnings for optional, 64-bit and super-
* visor instructions: -mo, -m64, -ms.
* v0.5 (12.10.97) phx
* Option -D defines symbols. If an '=' is missing, a default
* value of '1' will be assigned. Assignment of symbols, which
* are defined later in the source, is also allowed.
* v0.4 (05.07.97) phx
* Program returns EXIT_FAILURE if an error occurs.
* -V prints only version and build string and no instructions.
* Base address for absolute code may be set with -B option.
* EHF support.
* New option -I to specify some include paths.
* Option -x automatically declares unknown symbols as
* externally defined.
* v0.2 (25.03.97) phx
* Writes ELF object for 32-bit PowerPC big-endian. Either absolute
* or ELF output format may be selected. ELF is default for all
* currently supported platforms. PPCasm supports nine different
* relocation types (there are much more...).
* Compiles and works also under NetBSD/amiga (68k).
* Changed function declaration to 'new style' in all sources
* (to avoid problems with '...' for example).
* Supports multiple output formats. Currently Absolute and ELF.
* v0.1 (11.03.97) phx
* First test version with all PowerPC instructions and most
* important directives. Only raw, absolute output.
* v0.0 (14.02.97) phx
* File created. Project started.
*/
#define MAIN_C
#include "ppcasm.h"
struct GlobalVars gvars;
void cleanup(struct GlobalVars *);
static char *default_destname(struct GlobalVars *);
static void reset_sections(struct GlobalVars *);
static char *get_option_arg(int,char *[],int *);
static void write_object(struct GlobalVars *);
main(int argc,char *argv[])
{
struct GlobalVars *gv = &gvars;
int i,j;
char *buf;
char *stdassgn = "1"; /* default assignment for user definitions */
struct UserDefine *udn;
/* initialize and set default values */
memset(gv,0,sizeof(struct GlobalVars));
gv->maxerrors = DEF_MAXERRORS;
gv->output = OFMT_DEFAULT; /* default output format */
initlist(&gv->sourcelist);
initlist(&gv->sectionlist);
initlist(&gv->userdeflist);
if (argc<2 || (argc==2 && *argv[1]=='?')) {
show_usage();
exit(EXIT_SUCCESS);
}
for (i=1; i<argc; i++) {
if (*argv[i] == '-') {
/* option detected */
switch (argv[i][1]) {
case 'V': /* show version */
show_version();
exit(EXIT_SUCCESS);
case 'o': /* set output file */
if (!(gv->dest_name = get_option_arg(argc,argv,&i)))
error(3); /* missing output file name */
break;
case 'w': /* suppress warnings */
gv->dontwarn = TRUE;
break;
case 'x': /* auto extern */
gv->autoextern = TRUE;
break;
case 'R': /* don't predefine register symbols, etc. */
gv->noregsymbols = TRUE;
break;
case 'X': /* no extended mnemonics */
gv->noextmnemo = TRUE;
break;
case 'F': /* set output format (0=abs, 1=elf, 2=ehf, ... ) */
if (buf = get_option_arg(argc,argv,&i)) {
if ((j = atoi(buf)) > OFMT_LAST)
error(49,j); /* unknown output format */
else
gv->output = j;
}
else
error(48,'F'); /* option -F: argument expected */
break;
case 'O': /* set optimization level (0=none, ...) */
if (buf = get_option_arg(argc,argv,&i))
gv->opt = (uint32)atoi(buf);
else
error(48,'O'); /* option -O: argument expected */
break;
case 'I': /* add include path */
for (j=0; j<MAX_INCPATHS; j++) {
if (gv->incpaths[j] == NULL) {
if (!(gv->incpaths[j] = get_option_arg(argc,argv,&i)))
error(48,'I'); /* option -I: argument expected */
break;
}
}
if (j >= MAX_INCPATHS) /* path was ignored */
error(51,MAX_INCPATHS,get_option_arg(argc,argv,&i));
break;
case 'B': /* base address for absolute code */
if (buf = get_option_arg(argc,argv,&i)) {
if (!(sscanf(buf,"%li",(long *)&gv->absbase)))
error(54,'B'); /* option -B: integer expected */
}
else
error(48,'B'); /* option -B: argument expected */
break;
case 'D': /* define a symbol */
if (buf = get_option_arg(argc,argv,&i)) {
buf = getsymbol(gv,buf);
if (*gv->strbuf) {
buf = skipspaces(buf);
if (*buf == '=')
buf = skipspaces(++buf);
else
buf = stdassgn;
udn = alloc(sizeof(struct UserDefine));
udn->line = alloc(8 + strlen(gv->strbuf) + strlen(buf));
sprintf(udn->line,".set %s,%s\n",gv->strbuf,buf);
addtail(&gv->userdeflist,&udn->n);
}
else
error(56,'D'); /* option -D: symbol name expected */
}
else
error(48,'D'); /* option -D: argument expected */
break;
case 'm': /* -m set assembler mode */
if (buf = get_option_arg(argc,argv,&i)) {
if (!strcmp(buf,"64")) {
gv->sixtyfourmode = TRUE;
break;
}
else if (*buf == 'o') {
gv->optinstrmode = TRUE;
break;
}
else if (*buf == 's') {
gv->supermode = TRUE;
break;
}
}
error(57,buf); /* Unknown assembler mode -mX */
break;
default:
printf("Unknown option -%c ignored.\n",argv[i][1]);
break;
}
}
else {
/* source file name */
if (gv->source_name)
error(4); /* multiple source file names detected */
gv->source_name = argv[i];
}
}
if (!gv->source_name)
error(2); /* missing source file name */
if (!gv->dest_name)
gv->dest_name = default_destname(gv);
/* initialization */
init_hashtables(gv);
/* assemble */
exec_pass1(gv);
for (;;) {
gv->anotherpass = FALSE;
exec_pass2(gv);
if (!gv->anotherpass)
break;
/* another pass is required! */
reset_sections(gv);
}
/* write output file */
write_object(gv);
cleanup(gv);
}
static void reset_sections(struct GlobalVars *gv)
/* free section contents, all xrefs and relocations */
{
struct Section *nexts,*sec=(struct Section *)gv->sectionlist.first;
struct node *n;
while (nexts = (struct Section *)sec->n.next) {
while (n = remhead(&sec->reloclist))
free(n);
while (n = remhead(&sec->xreflist))
free(n);
if (!(sec->flags & SF_UNINITIALIZED) && sec->contents) {
free(sec->contents);
sec->data = sec->contents = NULL;
}
sec = nexts;
}
}
static char *default_destname(struct GlobalVars *gv)
/* make default output file name from source file name */
{
char dname[STRBUFSIZE];
int i;
strncpy(dname,gv->source_name,STRBUFSIZE-1);
i = strlen(dname